'use strict';

/* globals MediaRecorder */

// Spec is at http://dvcs.w3.org/hg/dap/raw-file/tip/media-stream-capture/RecordingProposal.html

navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;


if(getBrowser() == "Chrome"){
    var constraints = {"audio": true, "video": {  "mandatory": {  "minWidth": 640,  "maxWidth": 640, "minHeight": 480,"maxHeight": 480 }, "optional": [] } };//Chrome
}else if(getBrowser() == "Firefox"){
    var constraints = {audio: false, video: {  width: { min: 640, ideal: 640, max: 640 },  height: { min: 480, ideal: 480, max: 480 }}}; //Firefox
}

var recBtn = document.querySelector('button#rec');
var pauseResBtn = document.querySelector('button#pauseRes');
var stopBtn = document.querySelector('button#stop');

var videoElement = document.querySelector('video');
var dataElement = document.querySelector('#data');
var downloadLink = document.querySelector('a#downloadLink');

videoElement.controls = false;

function errorCallback(error){
    console.log('navigator.getUserMedia error: ', error);    
}

/*
var mediaSource = new MediaSource();
mediaSource.addEventListener('sourceopen', handleSourceOpen, false);
var sourceBuffer;
*/

var mediaRecorder;
var chunks = [];
var count = 0;

var wsurl = "ws://192.168.0.146:6000"
var ws = null;
function createWs(){
    var url = wsurl; 
    if ('WebSocket' in window) {  
           ws = new WebSocket(url);  
    } else if ('MozWebSocket' in window) {  
           ws = new MozWebSocket(url);  
    } else {  
           console.log("您的浏览器不支持WebSocket。");  
           return ;  
    }  
}
function init() {  
       if (ws != null) {  
           console.log("现已连接");  
           return ;  
       }  
       createWs();
       ws.onopen = function() {  
           //设置发信息送类型为：ArrayBuffer  
           ws.binaryType = "arraybuffer";  
       }  
       ws.onmessage = function(e) {  
           console.log(e.data.toString());
       }  
       ws.onclose = function(e) {  
           console.log("onclose: closed");
           ws = null;
           createWs(); //这个函数在这里之所以再次调用，是为了解决视频传输的过程中突发的连接断开问题。
       }  
       ws.onerror = function(e) {  
           console.log("onerror: error");  
           ws = null;
           createWs(); //同上面的解释
       }  
} 

$(document).ready(function(){
    init();
})

function startRecording(stream) {
    log('Start recording...');
    if (typeof MediaRecorder.isTypeSupported == 'function'){
        /*
            MediaRecorder.isTypeSupported is a function announced in https://developers.google.com/web/updates/2016/01/mediarecorder and later introduced in the MediaRecorder API spec http://www.w3.org/TR/mediastream-recording/
        */        //这里涉及到视频的容器以及编解码参数，这个与浏览器有密切的关系
        if (MediaRecorder.isTypeSupported('video/webm;codecs=vp9')) {
          var options = {mimeType: 'video/webm;codecs=h264'};
        } else if (MediaRecorder.isTypeSupported('video/webm;codecs=h264')) {
          var options = {mimeType: 'video/webm;codecs=h264'};
        } else  if (MediaRecorder.isTypeSupported('video/webm;codecs=vp8')) {
          var options = {mimeType: 'video/webm;codecs=vp8'};
        }
        log('Using '+options.mimeType);
        mediaRecorder = new MediaRecorder(stream, options);
    }else{
        log('isTypeSupported is not supported, using default codecs for browser');
        mediaRecorder = new MediaRecorder(stream);
    }

    pauseResBtn.textContent = "Pause";

    mediaRecorder.start(10);

    var url = window.URL || window.webkitURL;
    videoElement.src = url ? url.createObjectURL(stream) : stream;
    videoElement.play();
        //这个地方，是视频数据捕获好了后，会触发MediaRecorder一个dataavailable的Event，在这里做视频数据的采集工作，主要是基于Blob进行转写，利用FileReader进行读取。FileReader一定    //要注册loadend的监听器，或者写onload的函数。在loadend的监听函数里面，进行格式转换，方便websocket进行数据传输，因为websocket的数据类型支持blob以及arrayBuffer，我们这里用    //的是arrayBuffer，所以，将视频数据的Blob转写为Unit8Buffer，便于websocket的后台服务用ByteBuffer接收。
    mediaRecorder.ondataavailable = function(e) {
        //log('Data available...');
        //console.log(e.data);
        //console.log(e.data.type);
        //console.log(e);
        chunks.push(e.data);
        var reader = new FileReader();
        reader.addEventListener("loadend", function() {
            //reader.result是一个含有视频数据流的Blob对象
            var buf = new Uint8Array(reader.result);
            console.log(reader.result);    
            if(reader.result.byteLength > 0){        //加这个判断，是因为有很多数据是空的，这个没有必要发到后台服务器，减轻网络开销，提升性能吧。
                ws.send(buf);
            }
        });
        reader.readAsArrayBuffer(e.data);
    };

    mediaRecorder.onerror = function(e){
        log('Error: ' + e);        
    };


    mediaRecorder.onstart = function(){
        log('Started & state = ' + mediaRecorder.state);
    };

    mediaRecorder.onstop = function(){
        log('Stopped  & state = ' + mediaRecorder.state);

        var blob = new Blob(chunks, {type: "video/webm"});
        chunks = [];

        var videoURL = window.URL.createObjectURL(blob);

        downloadLink.href = videoURL;
        videoElement.src = videoURL;
        downloadLink.innerHTML = 'Download video file';

        var rand =  Math.floor((Math.random() * 10000000));
        var name  = "video_"+rand+".webm" ;

        downloadLink.setAttribute( "download", name);
        downloadLink.setAttribute( "name", name);
    };

    mediaRecorder.onpause = function(){
        log('Paused & state = ' + mediaRecorder.state);
    }

    mediaRecorder.onresume = function(){
        log('Resumed  & state = ' + mediaRecorder.state);
    }

    mediaRecorder.onwarning = function(e){
        log('Warning: ' + e);
    };
}

//function handleSourceOpen(event) {
//  console.log('MediaSource opened');
//  sourceBuffer = mediaSource.addSourceBuffer('video/webm; codecs="vp9"');
//  console.log('Source buffer: ', sourceBuffer);
//}
//点击按钮，启动视频流的采集。重点是getUserMedia函数使用。本案例中，视频采集的入口，是点击页面上的record按钮，也就是下面这个函数的逻辑。
function onBtnRecordClicked (){
    if (typeof MediaRecorder === 'undefined' || !navigator.getUserMedia) {
        alert('MediaRecorder not supported on your browser, use Firefox 30 or Chrome 49 instead.');
    }else {
        navigator.getUserMedia(constraints, startRecording, errorCallback);
        recBtn.disabled = true;
        pauseResBtn.disabled = false;
        stopBtn.disabled = false;
    }
}

function onBtnStopClicked(){
    mediaRecorder.stop();
    videoElement.controls = true;

    recBtn.disabled = false;
    pauseResBtn.disabled = true;
    stopBtn.disabled = true;
}

function onPauseResumeClicked(){
    if(pauseResBtn.textContent === "Pause"){
        console.log("pause");
        pauseResBtn.textContent = "Resume";
        mediaRecorder.pause();
        stopBtn.disabled = true;
    }else{
        console.log("resume");
        pauseResBtn.textContent = "Pause";
        mediaRecorder.resume();
        stopBtn.disabled = false;
    }
    recBtn.disabled = true;
    pauseResBtn.disabled = false;
}


function log(message){
    dataElement.innerHTML = dataElement.innerHTML+'<br>'+message ;
}



//browser ID
function getBrowser(){
    var nVer = navigator.appVersion;
    var nAgt = navigator.userAgent;
    var browserName  = navigator.appName;
    var fullVersion  = ''+parseFloat(navigator.appVersion);
    var majorVersion = parseInt(navigator.appVersion,10);
    var nameOffset,verOffset,ix;

    // In Opera, the true version is after "Opera" or after "Version"
    if ((verOffset=nAgt.indexOf("Opera"))!=-1) {
     browserName = "Opera";
     fullVersion = nAgt.substring(verOffset+6);
     if ((verOffset=nAgt.indexOf("Version"))!=-1)
       fullVersion = nAgt.substring(verOffset+8);
    }
    // In MSIE, the true version is after "MSIE" in userAgent
    else if ((verOffset=nAgt.indexOf("MSIE"))!=-1) {
     browserName = "Microsoft Internet Explorer";
     fullVersion = nAgt.substring(verOffset+5);
    }
    // In Chrome, the true version is after "Chrome"
    else if ((verOffset=nAgt.indexOf("Chrome"))!=-1) {
     browserName = "Chrome";
     fullVersion = nAgt.substring(verOffset+7);
    }
    // In Safari, the true version is after "Safari" or after "Version"
    else if ((verOffset=nAgt.indexOf("Safari"))!=-1) {
     browserName = "Safari";
     fullVersion = nAgt.substring(verOffset+7);
     if ((verOffset=nAgt.indexOf("Version"))!=-1)
       fullVersion = nAgt.substring(verOffset+8);
    }
    // In Firefox, the true version is after "Firefox"
    else if ((verOffset=nAgt.indexOf("Firefox"))!=-1) {
     browserName = "Firefox";
     fullVersion = nAgt.substring(verOffset+8);
    }
    // In most other browsers, "name/version" is at the end of userAgent
    else if ( (nameOffset=nAgt.lastIndexOf(' ')+1) <
           (verOffset=nAgt.lastIndexOf('/')) )
    {
     browserName = nAgt.substring(nameOffset,verOffset);
     fullVersion = nAgt.substring(verOffset+1);
     if (browserName.toLowerCase()==browserName.toUpperCase()) {
      browserName = navigator.appName;
     }
    }
    // trim the fullVersion string at semicolon/space if present
    if ((ix=fullVersion.indexOf(";"))!=-1)
       fullVersion=fullVersion.substring(0,ix);
    if ((ix=fullVersion.indexOf(" "))!=-1)
       fullVersion=fullVersion.substring(0,ix);

    majorVersion = parseInt(''+fullVersion,10);
    if (isNaN(majorVersion)) {
     fullVersion  = ''+parseFloat(navigator.appVersion);
     majorVersion = parseInt(navigator.appVersion,10);
    }
    return browserName;
}